/*
 * mutex.c
 *
 *  Created on: May 30, 2013
 *      Author: David
 */

#include <stdio.h>
#include "mutex.h"
#include "pcb.h"

char* mutex_init(Mutex* this) {
  this->atomic = PTHREAD_MUTEX_INITIALIZER;
  this->queue = newQueueConstructor();
  this->locked = 0;
  this->lock = mutex_lock;
  this->unlock = mutex_unlock;
  return 0;
}

char* mutex_lock(Mutex* this, PCBPtr process) {
  pthread_mutex_lock(&(this->atomic));
  if(process == 0) return "[mutex_lock] process cannot be blank";
  if( ! this->locked ) {
    this->locked = process;
  } else {
    this->queue->enqueue(this->queue,(int)process);
  }
  pthread_mutex_unlock(&(this->atomic));
  return 0;
}

char* mutex_unlock(Mutex* this, PCBPtr process) {
  pthread_mutex_lock(&(this->atomic));

  //error handling
  if(process == 0) return "[mutex_unlock] process cannot be blank";
  if( ! this->locked ) return "[mutex_unlock] process not locked";
  if( this->locked != process ) return "[mutex_unlock] unlocking process != locking process";

  if( ! this->queue->empty(this->queue) ) {
    this->locked = (PCBPtr)this->queue->dequeue(this->queue);
  } else {
    this->locked = (PCBPtr)0;
  }

  pthread_mutex_unlock(&(this->atomic));
  return 0;
}

  /*
int main(void) {
  char* error = 0;
  Mutex mutex;
  error = mutex_init(&mutex); if(error) printw("%s\n",error);
  printw("prev    -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  error = mutex.lock(&mutex,1); if(error) printw("%s\n",error);
  printw("lock  1 -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  error = mutex.unlock(&mutex,1); if(error) printw("%s\n",error);
  printw("ulock 1 -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  error = mutex.lock(&mutex,2); if(error) printw("%s\n",error);
  printw("lock  2 -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  error = mutex.lock(&mutex,3); if(error) printw("%s\n",error);
  printw("lock  3 -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  error = mutex.lock(&mutex,4); if(error) printw("%s\n",error);
  printw("lock  4 -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  //this one should spit out an error
  error = mutex.unlock(&mutex,3); if(error) printw("%s\n",error);
  printw("ulock 3 -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  error = mutex.unlock(&mutex,2); if(error) printw("%s\n",error);
  printw("ulock 2 -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  error = mutex.unlock(&mutex,3); if(error) printw("%s\n",error);
  printw("ulock 3 -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  error = mutex.unlock(&mutex,4); if(error) printw("%s\n",error);
  printw("ulock 4 -> owner %d\n", mutex.locked);
  mutex.queue->display(mutex.queue);
  printw("-----------------\n");

  return 0;
}// */



